﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using ModelingProjectLib.Interfaces;

namespace INSAwarsWPF
{
    //[Serializable()]
    /** Représente l'ensemble de Joueurs de la Partie */
    public class EnsembleJoueursViewModel : ObservableCollection<JoueurViewModel>, INotifyPropertyChanged
    {
        //[field: NonSerializedAttribute()] 
        /** Utilitaires pour le binding */
        protected override event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        /** Enumerateur qui pointe sur le joueur courant */
        public IEnumerator<JoueurViewModel> EnumJoueur { get; private set; }

        /** GameViewModel dans lequel on utilise l'ensemble de joueurs */
        public GameViewModel Conteneur { get; private set; }

        public EnsembleJoueursViewModel(GameViewModel _gvm)
        {
            Conteneur = _gvm;
        }

        /** Fonction qui positionne l'énumérateur sur le joueur courant. Appelée après le remplissage de la liste */
        public void DoApresRemplissage()
        {
            // la liste est complète : on peut prendre un énumérateur pour le joueur courant
            EnumJoueur = this.GetEnumerator();
            EnumJoueur.MoveNext(); // on va sur le premier élément : IMPORTANT
        }

        /** Passe au joueur suivant et met à jour les informations sur l'écran */
        public void joueurSuivant()
        {
            //Conteneur.PartieCourante.JoueurCourant.Civilisation.
           
            JoueurViewModel joueurOld = JoueurCourant;
            if (joueurOld.HasUniteBougeable)
            {
                if (MessageBox.Show("Certaines de vos unités possèdent encore des points de mouvement. Voulez-vous vraiment terminer le tour ?", "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.No)
                {
                    Conteneur.View.focusOnSelectedUnite();
                    return;
                }
            }

            if (!EnumJoueur.MoveNext())
            {
                EnumJoueur.Reset();
                EnumJoueur.MoveNext();
            }

            JoueurViewModel joueurNew = JoueurCourant;

            // on effectue le changement de contexte pour la vue (sélection...)
            changementJoueur(joueurOld, joueurNew);

            // on met à jour le modèle
            Conteneur.PartieCourante.joueurSuivant();


        }

        /** JoueurViewModel courant */
        public JoueurViewModel JoueurCourant { get { return EnumJoueur.Current; } }

        /** Méthode privée qui effectue le changement de contexte entre les joueurs :
         * sauvegarde des dernières unités sélectionnées */
        private void changementJoueur(JoueurViewModel _old, JoueurViewModel _new)
        {
            // a gérer : si l'unité est détruite au tour d'avant...
            _old.DerniereCaseSelectionnee = Conteneur.SelectedCase;
            _old.DerniereUniteSelectionnee = Conteneur.SelectedCase.SelectedUnite;

            Conteneur.SelectedCase = _new.DerniereCaseSelectionnee;
            Conteneur.SelectedCase.SelectedUnite = _new.DerniereUniteSelectionnee;



            // keyboard focus :
            Conteneur.View.focusOnSelectedUnite();

            // initialisation du nouveau tour du joueur
            _new.beginNouveauTour();

            RaisePropertyChanged("JoueurCourant");
        }

        /** Méthode utilitaire qui retourne le JoueurViewModel correspondant au Joueur _joueur */
        public JoueurViewModel getJoueurVMFromJoueur(Joueur _joueur) {
            JoueurViewModel jvmRes = null;

            foreach (JoueurViewModel jvm in this)
            {
                if (jvm.JoueurModel == _joueur)
                {
                    jvmRes = jvm; break; // trouvera forcément le jvm
                }
            }

            return jvmRes;
        }

        /** Teste si le joueur correspondans à joueur est en vie dans l'ensemble */
        public bool joueurIsEnVie(Joueur joueur)
        {
            JoueurViewModel jvm = getJoueurVMFromJoueur(joueur);
            return jvm.Unites.Count > 0 || jvm.Villes.Count > 0;
        }

        /** Supprime le joueur correspondant à joueur dans l'ensemble */
        public void supprimerJoueur(Joueur joueur)
        {
            JoueurViewModel joueurASupprimer = getJoueurVMFromJoueur(joueur);

            if (joueurASupprimer == JoueurCourant)
                joueurSuivant();

            Remove(joueurASupprimer);
            Conteneur.PartieCourante.ListJoueurs.Remove(joueurASupprimer.JoueurModel);

            MessageBox.Show(joueurASupprimer.JoueurModel.Nom + " a perdu !");

            if (Count == 1)
            {
                MessageBox.Show(this[0].JoueurModel.Nom + " a gagné ! Félicitations");
                Conteneur.IsPartieFinie = true;
                Conteneur.View.Close();
            }
        }
    }
}
